/*------------------------------------------------------------------------
* Seedset-generator
* $Id$
* Copyright (c) 2008 Regents of the University of Minnesota.
* All Rights Reserved by the Regents of the University of Minnesota.
* This file contains Original Code and/or Modifications of Original
* Code as defined in the MAGNET Public Source License, which is
* available at http://www.cs.umn.edu/magnet/source_license_v1.txt.
* You may not use this file except in compliance with the License.
*------------------------------------------------------------------------
*/

package edu.umn.cs.tac.seedsetgen;

import javax.swing.JEditorPane;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.UIManager;

import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeNode;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Color;

import java.util.Random;
import java.util.Enumeration;

import java.io.*;

public class SeedTree extends JPanel implements ActionListener, TreeSelectionListener
{
    private JTree tree;
    private SeedInfoBox seedInfoBox;
    private JPanel buttonPanel;

    private static boolean DEBUG = false;

    private static String CONTROL_COMMAND = "control";
    private static String RANDOM_COMMAND = "random";
    private static String LOAD_COMMAND = "load";
    private static String SAVE_COMMAND = "save";
    private static String SEED_FILE_NAME = "seedData1.dat";

    //Optionally play with line styles.  Possible values are
    //"Angled" (the default), "Horizontal", and "None".
    private static boolean playWithLineStyle = false;
    private static String lineStyle = "Horizontal";

    //Optionally set the look and feel.
    private static boolean useSystemLookAndFeel = true;

    private Random random = new Random();

    public SeedTree()
    {
        //super(new GridLayout(1,0));
        super(new BorderLayout());

        //Create the nodes.
        DefaultMutableTreeNode top =
            new DefaultMutableTreeNode(new SeedParameter("Market Variables", true));
        createNodes(top);

        //Create a tree that allows one selection at a time.
        tree = new JTree(top);
        tree.getSelectionModel().setSelectionMode
            (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
        //tree.setShowsRootHandles(true); 

        //DO THIS FOR CUSTOM COLORS/IMAGES
        tree.setCellRenderer(new TreeNodeRenderer());

        //Listen for when the selection changes.
        tree.addTreeSelectionListener(this);

        if (playWithLineStyle)
        {
            System.out.println("line style = " + lineStyle);
            tree.putClientProperty("JTree.lineStyle", lineStyle);
        }

        //Create the scroll pane and add the tree to it. 
        JScrollPane treeView = new JScrollPane(tree);
        treeView.setPreferredSize(new Dimension(300, 300)); 
        add(treeView, BorderLayout.CENTER);

        //Create right panel
        //JPanel rightPanel = new JPanel(new GridLayout(0,1));
        //add(rightPanel, BorderLayout.LINE_END);

        //Create button panel
        buttonPanel = new JPanel(new GridLayout(0,1)); 
        //rightPanel.add(buttonPanel);
        add(buttonPanel, BorderLayout.LINE_START);

        JButton controlButton = new JButton("Control");
        controlButton.setForeground(new Color(150, 0, 0));
        controlButton.setActionCommand(CONTROL_COMMAND);
        controlButton.addActionListener(this);

        JButton randomButton = new JButton("Random");
        randomButton.setForeground(new Color(0,150,0));
        randomButton.setActionCommand(RANDOM_COMMAND);
        randomButton.addActionListener(this);

        JButton loadButton = new JButton("Load Seeds");
        loadButton.setActionCommand(LOAD_COMMAND);
        loadButton.addActionListener(this);

        JButton saveButton = new JButton("Save Seeds");
        saveButton.setActionCommand(SAVE_COMMAND);
        saveButton.addActionListener(this);

        buttonPanel.add(randomButton);
        buttonPanel.add(controlButton);
        buttonPanel.add(loadButton);
        buttonPanel.add(saveButton);

        //Create seed info panel
        seedInfoBox = new SeedInfoBox(this); 
        //rightPanel.add(seedInfoBox);
        add(seedInfoBox, BorderLayout.PAGE_END);
    }


    // Required for action when a button is pressed
    public void actionPerformed(ActionEvent e)
    {
        String command = e.getActionCommand();

        if (CONTROL_COMMAND.equals(command))
        {
            //Control button clicked
            //System.out.println("Control clicked.");
            setNodeControl(true, 0);
        }
        else if (RANDOM_COMMAND.equals(command))
        {
            //Remove button clicked
            //System.out.println("Random clicked.");
            setNodeControl(false, 0);
        }
        else if (LOAD_COMMAND.equals(command))
        {
            //Clear button clicked.
            //System.out.println("Load clicked.");
            loadSeedsFromFile();
        }
        else if (SAVE_COMMAND.equals(command))
        {
            //Calculate button clicked.
            //System.out.println("Save clicked.");
            printSeedsToFile();
        }

        updateGraphicalInfo();
    }


    public void updateGraphicalInfo()
    {
        //repaint tree colors and icons
        tree.repaint();

        int numSelected = tree.getSelectionCount();
        TreePath path = tree.getSelectionPath();

        if (path == null)
            return;

        //TODO: Print message if multiple selections

        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) (path.getLastPathComponent());
        SeedParameter currentParameter = (SeedParameter) selectedNode.getUserObject();
        seedInfoBox.printInfo(currentParameter);
    }

    //This executes when the "Control" or "Random" button is pressed.
    //It chooses a seed for all descendant nodes and/or the highlighted node.
    //
    //  toControl==true, seedToUse!=0  ->  control server using specified seed
    //  toControl==true, seedToUse==0  ->  control server, pick seed randomly 
    //  toControl==false  -> use random server (which picks seed randomly each game) 
    public void setNodeControl(boolean toControl, long seedToUse)
    {

        //Random control will always use seed 0.
        if (!toControl)
        {
            seedToUse = (long) 0;
        }

        Long seed = seedToUse; //if not specified, have server randomly pick a seed

        //If no path has been selected yet, automatically select the root.
        if (tree.getSelectionPaths() == null)
        {
            DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) (tree.getModel().getRoot());
            tree.setSelectionPath(new TreePath(rootNode));
        }

        //Get all paths that are selected
        TreePath[] treePath = tree.getSelectionPaths();

        //TODO: WE SHOULD REMOVE ANY PATHS THAT ARE A SUBSET OF ANOTHER PATH
        //[This will save time by preventing redundancy, but is not necessary]

        for (int i=0; i<treePath.length; i++)
        {
            //Get the last node in each path.
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)treePath[i].getLastPathComponent();

            //Get all descendants of that node.
            Enumeration descendants = selectedNode.postorderEnumeration();

            //Set descendendants to controlled/random
            while(descendants.hasMoreElements())
            {
                seed = seedToUse; //reset the seed each iteration.
                DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)descendants.nextElement();
                SeedParameter seedParam = (SeedParameter) (currentNode.getUserObject());

                if (currentNode.isLeaf())
                {
                    //Pick a seed for the controlled server.
                    //In the unlikely event that the seed picked is 0, pick another one.
                    //(0 is used to represent that the seed should be random).
                    while (toControl && seed==0)
                    {
                        seed = random.nextLong();
                    }
                    seedParam.setSeed(seed);					
                }
                setProperControlType(currentNode); //do this whether leaf or not
            }

            //Modify CONTROLLED? status of any ancestors whose descendants changed.
            TreeNode rootPath[] = selectedNode.getPath();
            for (int j=rootPath.length-1; j>=0; j--)
            {
                DefaultMutableTreeNode pathNode = (DefaultMutableTreeNode) (rootPath[j]);
                setProperControlType(pathNode);
            }
        }//all selections done
    }		



    //Determine if node is completely controlled, partially controlled, or random.
    //Set node to be whatever's appropriate.
    public void setProperControlType(DefaultMutableTreeNode currentNode)
    {
        SeedParameter seedParam = (SeedParameter) (currentNode.getUserObject());


        if(currentNode.isLeaf())
        { //will never be partially controlled
            if (seedParam.isRandom())
            {
                seedParam.setControlType(seedParam.RANDOM_TYPE);
            }
            else
            {
                seedParam.setControlType(seedParam.CONTROLLED_TYPE);
            }
            return;
        }

        //Determine control type of node.
        //Get children, see if they're controlled or random
        boolean pureControlled=true;
        boolean pureRandom=true;
        Enumeration children = currentNode.children();
        while(children.hasMoreElements())
        {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)children.nextElement();
            SeedParameter childParam = (SeedParameter)(childNode.getUserObject());
            if(childParam.controlType==0)
            {//random child
                pureControlled=false;
            }
            else if (childParam.controlType==1)
            {//controlled child
                pureRandom=false;
            }
            else
            { //partial child
                pureControlled=false;
                pureRandom=false;
            }
        }//finished cycling through children	

        if (pureRandom==true)
        {
            seedParam.setControlType(seedParam.RANDOM_TYPE);
        }
        else if (pureControlled==true)
        {
            seedParam.setControlType(seedParam.CONTROLLED_TYPE);
        }
        else
        {
            seedParam.setControlType(seedParam.PARTIAL_TYPE);
        }
    }



    //Print seeds to file
    public void printSeedsToFile()
    {
        DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) (tree.getModel().getRoot());
        Enumeration nodeEnum = rootNode.depthFirstEnumeration();
        DefaultMutableTreeNode currentNode;
        SeedParameter seedParam;
        long currentSeed;

        try
        {
            // Create file 
            FileWriter fstream = new FileWriter(SEED_FILE_NAME);
            BufferedWriter out = new BufferedWriter(fstream);

            //go through all nodes
            //if node is a leaf, document its seed.
            while(nodeEnum.hasMoreElements())
            {
                currentNode = (DefaultMutableTreeNode) (nodeEnum.nextElement());
                if(currentNode.isLeaf())
                {
                    //Print node's param to file
                    seedParam = (SeedParameter) (currentNode.getUserObject());
                    currentSeed = seedParam.getSeed();
                    //System.out.print(currentSeed+" ");
                    out.write(String.valueOf(currentSeed)+"\n");
                }
            }
            //Close the output stream
            out.close();
            System.out.println("Data saved to "+SEED_FILE_NAME);

        }
        catch (Exception e)
        {//Catch exception if any
            System.err.println("Error: " + e.getMessage());
        }
    }

    public void loadSeedsFromFile()
    {
        DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) (tree.getModel().getRoot());
        Enumeration nodeEnum = rootNode.depthFirstEnumeration();
        DefaultMutableTreeNode currentNode;
        SeedParameter seedParam;
        long currentSeed;

        try
        {
            //Open input stream
            FileReader fstream = new FileReader(SEED_FILE_NAME);
            BufferedReader in = new BufferedReader(fstream);


            //go through all nodes
            //if node is a leaf, document its seed.
            while(nodeEnum.hasMoreElements())
            {
                currentNode = (DefaultMutableTreeNode) (nodeEnum.nextElement());
                if(currentNode.isLeaf())
                {
                    //Print node's param to file
                    seedParam = (SeedParameter) (currentNode.getUserObject());
                    currentSeed = Long.parseLong(in.readLine().trim());
                    //System.out.println(currentSeed);
                    seedParam.setSeed(currentSeed);
                }

                //update contol data for all nodes in tree
                setProperControlType(currentNode);
            }
            //Close the output stream
            in.close();						
            System.out.println("Data loaded from "+SEED_FILE_NAME);

        }
        catch (Exception e)
        {//Catch exception if any
            System.err.println("Error: " + e.getMessage());
        }

        //update colors and icons
        updateGraphicalInfo();
    }


    /** Required by TreeSelectionListener interface. */
    public void valueChanged(TreeSelectionEvent e)
    {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
            tree.getLastSelectedPathComponent();

        if (node == null) return;

        SeedParameter seedParam = (SeedParameter) (node.getUserObject());
        seedInfoBox.setCurrentSeedParameter(seedParam);
        seedInfoBox.printInfo(seedParam);

    }


    private void createNodes(DefaultMutableTreeNode top)
    {
        DefaultMutableTreeNode gameParams = null;
        DefaultMutableTreeNode bank = null;
        DefaultMutableTreeNode storage = null;
        DefaultMutableTreeNode supplierParams = null;
        DefaultMutableTreeNode nominalCapacities = null;
        DefaultMutableTreeNode nominalCPU = null;
        DefaultMutableTreeNode nominalPintel = null;
        DefaultMutableTreeNode nominalIMD = null;
        DefaultMutableTreeNode nominalMboard = null;
        DefaultMutableTreeNode nominalBasus = null;
        DefaultMutableTreeNode nominalMacrostar = null;
        DefaultMutableTreeNode nominalMemory = null;
        DefaultMutableTreeNode nominalMEC = null;
        DefaultMutableTreeNode nominalQueenmax = null;
        DefaultMutableTreeNode nominalHardDisk = null;
        DefaultMutableTreeNode nominalWatergate = null;
        DefaultMutableTreeNode nominalMintor = null;
        DefaultMutableTreeNode dailyCapacities = null;
        DefaultMutableTreeNode dailyCPU = null;
        DefaultMutableTreeNode dailyLowCPU = null;
        DefaultMutableTreeNode dailyLowPintelCPU = null;
        DefaultMutableTreeNode dailyLowIMDCPU = null;
        DefaultMutableTreeNode dailyHighCPU = null;
        DefaultMutableTreeNode dailyHighPintelCPU = null;
        DefaultMutableTreeNode dailyHighIMDCPU = null;
        DefaultMutableTreeNode dailyMotherboard = null;
        DefaultMutableTreeNode dailyPintelMotherboard = null;
        DefaultMutableTreeNode dailyPintelBasusMotherboard = null;
        DefaultMutableTreeNode dailyPintelMacrostarMotherboard = null;
        DefaultMutableTreeNode dailyIMDMotherboard = null;
        DefaultMutableTreeNode dailyIMDBasusMotherboard = null;
        DefaultMutableTreeNode dailyIMDMacrostarMotherboard = null;
        DefaultMutableTreeNode dailyMemory = null;
        DefaultMutableTreeNode dailyLowMemory = null;
        DefaultMutableTreeNode dailyLowMECMemory = null;
        DefaultMutableTreeNode dailyLowQueenmaxMemory = null;
        DefaultMutableTreeNode dailyHighMemory = null;
        DefaultMutableTreeNode dailyHighMECMemory = null;
        DefaultMutableTreeNode dailyHighQueenmaxMemory = null;
        DefaultMutableTreeNode dailyHardDisk = null;
        DefaultMutableTreeNode dailyLowHardDisk = null;
        DefaultMutableTreeNode dailyLowWatergateHardDisk = null;
        DefaultMutableTreeNode dailyLowQueenmaxHardDisk = null;		
        DefaultMutableTreeNode dailyHighHardDisk = null;
        DefaultMutableTreeNode dailyHighWatergateHardDisk = null;
        DefaultMutableTreeNode dailyHighQueenmaxHardDisk = null;
        DefaultMutableTreeNode customerParams = null;		
        DefaultMutableTreeNode initialDemand = null;
        DefaultMutableTreeNode dailyDemand = null;
        DefaultMutableTreeNode dailySegDemand = null;
        DefaultMutableTreeNode dailyProdDemand = null;
        DefaultMutableTreeNode dailyRfqInfo = null;

        DefaultMutableTreeNode dailySegDemandLow = null;
        DefaultMutableTreeNode dailySegDemandMed = null;
        DefaultMutableTreeNode dailySegDemandHigh = null;
        DefaultMutableTreeNode dailyProdDemandLow = null;
        DefaultMutableTreeNode dailyProdDemandMed = null;
        DefaultMutableTreeNode dailyProdDemandHigh = null;
        DefaultMutableTreeNode dailyRfqInfoLow = null;
        DefaultMutableTreeNode dailyRfqInfoMed = null;
        DefaultMutableTreeNode dailyRfqInfoHigh = null;
        DefaultMutableTreeNode tieBreaker = null;

        //GAME PARAMS
        gameParams = new DefaultMutableTreeNode(new SeedParameter("Initial", true));
        top.add(gameParams);

        //bank interest
        bank = new DefaultMutableTreeNode(new SeedParameter("Bank Interest"));
        gameParams.add(bank);

        //storage interest
        storage = new DefaultMutableTreeNode(new SeedParameter("Storage Interest"));
        gameParams.add(storage);

        //SUPPLIER
        supplierParams = new DefaultMutableTreeNode(new SeedParameter("Supply", true));
        top.add(supplierParams);

        //nominal supplier capacities
        nominalCapacities = new DefaultMutableTreeNode(new SeedParameter("Nominal Capacities", true));
        supplierParams.add(nominalCapacities);

        //cpu
        nominalCPU = new DefaultMutableTreeNode(new SeedParameter("CPU"));
        nominalCapacities.add(nominalCPU);

        //pintel
        nominalPintel = new DefaultMutableTreeNode(new SeedParameter("Pintel"));
        nominalCPU.add(nominalPintel);

        //imd
        nominalIMD = new DefaultMutableTreeNode(new SeedParameter("IMD"));
        nominalCPU.add(nominalIMD);

        //mboard
        nominalMboard = new DefaultMutableTreeNode(new SeedParameter("Motherboard", true));
        nominalCapacities.add(nominalMboard);

        //basus
        nominalBasus = new DefaultMutableTreeNode(new SeedParameter("Basus"));
        nominalMboard.add(nominalBasus);

        //macrostar
        nominalMacrostar = new DefaultMutableTreeNode(new SeedParameter("Macrostar"));
        nominalMboard.add(nominalMacrostar);

        //memory
        nominalMemory = new DefaultMutableTreeNode(new SeedParameter("Memory", true));
        nominalCapacities.add(nominalMemory);

        //MEC
        nominalMEC = new DefaultMutableTreeNode(new SeedParameter("MEC"));
        nominalMemory.add(nominalMEC);

        //Queenmax
        nominalQueenmax = new DefaultMutableTreeNode(new SeedParameter("Queenmax"));
        nominalMemory.add(nominalQueenmax);

        //hard disk
        nominalHardDisk = new DefaultMutableTreeNode(new SeedParameter("Hard Disk", true));
        nominalCapacities.add(nominalHardDisk);

        //Watergate
        nominalWatergate = new DefaultMutableTreeNode(new SeedParameter("Watergate"));
        nominalHardDisk.add(nominalWatergate);

        //Mintor
        nominalMintor = new DefaultMutableTreeNode(new SeedParameter("Mintor"));
        nominalHardDisk.add(nominalMintor);

        //daily supplier capacities
        dailyCapacities = new DefaultMutableTreeNode(new SeedParameter("Daily Capacities", true));
        supplierParams.add(dailyCapacities);

        //cpu
        dailyCPU = new DefaultMutableTreeNode(new SeedParameter("CPU", true));
        dailyCapacities.add(dailyCPU);

        //lowCPU
        dailyLowCPU = new DefaultMutableTreeNode(new SeedParameter("Low", true));
        dailyCPU.add(dailyLowCPU);

        //lowPintelCPU
        dailyLowPintelCPU = new DefaultMutableTreeNode(new SeedParameter("Pintel"));
        dailyLowCPU.add(dailyLowPintelCPU);

        //lowIMDCPU
        dailyLowIMDCPU = new DefaultMutableTreeNode(new SeedParameter("IMD"));
        dailyLowCPU.add(dailyLowIMDCPU);

        //highCPU
        dailyHighCPU = new DefaultMutableTreeNode(new SeedParameter("High", true));
        dailyCPU.add(dailyHighCPU);

        //highPintelCPU
        dailyHighPintelCPU = new DefaultMutableTreeNode(new SeedParameter("Pintel"));
        dailyHighCPU.add(dailyHighPintelCPU);

        //highIMDCPU
        dailyHighIMDCPU = new DefaultMutableTreeNode(new SeedParameter("IMD"));
        dailyHighCPU.add(dailyHighIMDCPU);

        //mboard
        dailyMotherboard = new DefaultMutableTreeNode(new SeedParameter("Motherboard", true));
        dailyCapacities.add(dailyMotherboard);

        //PintelMotherboard
        dailyPintelMotherboard = new DefaultMutableTreeNode(new SeedParameter("For Pintel", true));
        dailyMotherboard.add(dailyPintelMotherboard);

        //PintelBasusMotherboard
        dailyPintelBasusMotherboard = new DefaultMutableTreeNode(new SeedParameter("Basus"));
        dailyPintelMotherboard.add(dailyPintelBasusMotherboard);

        //PintelMacrostarMotherboard
        dailyPintelMacrostarMotherboard = new DefaultMutableTreeNode(new SeedParameter("Macrostar"));
        dailyPintelMotherboard.add(dailyPintelMacrostarMotherboard);

        //IMDMotherboard
        dailyIMDMotherboard = new DefaultMutableTreeNode(new SeedParameter("For IMD", true));
        dailyMotherboard.add(dailyIMDMotherboard);

        //IMDBasusMotherboard
        dailyIMDBasusMotherboard = new DefaultMutableTreeNode(new SeedParameter("Basus"));
        dailyIMDMotherboard.add(dailyIMDBasusMotherboard);

        //IMDMacrostarMotherboard
        dailyIMDMacrostarMotherboard = new DefaultMutableTreeNode(new SeedParameter("Macrostar"));
        dailyIMDMotherboard.add(dailyIMDMacrostarMotherboard);


        //memory
        dailyMemory = new DefaultMutableTreeNode(new SeedParameter("Memory", true));
        dailyCapacities.add(dailyMemory);

        //lowMemory
        dailyLowMemory = new DefaultMutableTreeNode(new SeedParameter("Low", true));
        dailyMemory.add(dailyLowMemory);

        //lowMECMemory
        dailyLowMECMemory = new DefaultMutableTreeNode(new SeedParameter("MEC"));
        dailyLowMemory.add(dailyLowMECMemory);

        //lowQueenmaxMemory
        dailyLowQueenmaxMemory = new DefaultMutableTreeNode(new SeedParameter("Queenmax"));
        dailyLowMemory.add(dailyLowQueenmaxMemory);

        //highMemory
        dailyHighMemory = new DefaultMutableTreeNode(new SeedParameter("High", true));
        dailyMemory.add(dailyHighMemory);

        //highMECMemory
        dailyHighMECMemory = new DefaultMutableTreeNode(new SeedParameter("MEC"));
        dailyHighMemory.add(dailyHighMECMemory);

        //highQueenmaxMemory
        dailyHighQueenmaxMemory = new DefaultMutableTreeNode(new SeedParameter("Queenmax"));
        dailyHighMemory.add(dailyHighQueenmaxMemory);

        //hard disk
        dailyHardDisk = new DefaultMutableTreeNode(new SeedParameter("Hard Disk", true));
        dailyCapacities.add(dailyHardDisk);

        //lowHardDisk
        dailyLowHardDisk = new DefaultMutableTreeNode(new SeedParameter("Low", true));
        dailyHardDisk.add(dailyLowHardDisk);

        //lowWatergateHardDisk
        dailyLowWatergateHardDisk = new DefaultMutableTreeNode(new SeedParameter("Watergate"));
        dailyLowHardDisk.add(dailyLowWatergateHardDisk);

        //lowWatergateHardDisk
        dailyLowQueenmaxHardDisk = new DefaultMutableTreeNode(new SeedParameter("Queenmax"));
        dailyLowHardDisk.add(dailyLowQueenmaxHardDisk);

        //highHardDisk
        dailyHighHardDisk = new DefaultMutableTreeNode(new SeedParameter("High", true));
        dailyHardDisk.add(dailyHighHardDisk);

        //highWatergateHardDisk
        dailyHighWatergateHardDisk = new DefaultMutableTreeNode(new SeedParameter("Watergate"));
        dailyHighHardDisk.add(dailyHighWatergateHardDisk);

        //highQueenmaxHardDisk
        dailyHighQueenmaxHardDisk = new DefaultMutableTreeNode(new SeedParameter("Queenmax"));
        dailyHighHardDisk.add(dailyHighQueenmaxHardDisk);

        //CUSTOMER
        customerParams = new DefaultMutableTreeNode(new SeedParameter("Demand", true));
        top.add(customerParams);

        //Day 0 RFQs
        initialDemand = new DefaultMutableTreeNode(new SeedParameter("Initial Demand"));
        customerParams.add(initialDemand);

        dailyDemand = new DefaultMutableTreeNode(new SeedParameter("Daily Demand", true));
        customerParams.add(dailyDemand);

        dailySegDemand = new DefaultMutableTreeNode(new SeedParameter("# RFQs for Segments"));
        dailyDemand.add(dailySegDemand);

        dailyProdDemand = new DefaultMutableTreeNode(new SeedParameter("# RFQs for Products"));
        dailyDemand.add(dailyProdDemand);

        dailyRfqInfo = new DefaultMutableTreeNode(new SeedParameter("RFQ Info (qty, dueDate, RP, penalty)"));
        dailyDemand.add(dailyRfqInfo);


        dailySegDemandLow = new DefaultMutableTreeNode(new SeedParameter("Low Segment"));
        dailySegDemand.add(dailySegDemandLow);
        dailySegDemandMed = new DefaultMutableTreeNode(new SeedParameter("Medium Segment"));
        dailySegDemand.add(dailySegDemandMed);
        dailySegDemandHigh = new DefaultMutableTreeNode(new SeedParameter("High Segment"));
        dailySegDemand.add(dailySegDemandHigh);

        dailyProdDemandLow = new DefaultMutableTreeNode(new SeedParameter("Low Segment"));
        dailyProdDemand.add(dailyProdDemandLow);
        dailyProdDemandMed = new DefaultMutableTreeNode(new SeedParameter("Medium Segment"));
        dailyProdDemand.add(dailyProdDemandMed);
        dailyProdDemandHigh = new DefaultMutableTreeNode(new SeedParameter("High Segment"));
        dailyProdDemand.add(dailyProdDemandHigh);

        dailyRfqInfoLow = new DefaultMutableTreeNode(new SeedParameter("Low Segment"));
        dailyRfqInfo.add(dailyRfqInfoLow);
        dailyRfqInfoMed = new DefaultMutableTreeNode(new SeedParameter("Medium Segment"));
        dailyRfqInfo.add(dailyRfqInfoMed);
        dailyRfqInfoHigh = new DefaultMutableTreeNode(new SeedParameter("High Segment"));
        dailyRfqInfo.add(dailyRfqInfoHigh);

        tieBreaker = new DefaultMutableTreeNode(new SeedParameter("Same Offer Tiebreaker"));
        customerParams.add(tieBreaker);
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI()
    {
        if (useSystemLookAndFeel)
        {
            try
            {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            }
            catch (Exception e)
            {
                System.err.println("Couldn't use system look and feel.");
            }
        }

        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        JFrame frame = new JFrame("Controlled Server Setup");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        SeedTree newContentPane = new SeedTree();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
